package cz.tomasdvorak.cars.pages.expenses;

import cz.tomasdvorak.cars.auth.Auth;
import cz.tomasdvorak.cars.dto.*;
import cz.tomasdvorak.cars.pages.BasePage;
import cz.tomasdvorak.cars.utils.Lists;
import cz.tomasdvorak.cars.wicket.components.breadcrumbs.BreadcrumbItem;
import cz.tomasdvorak.cars.wicket.components.table.AbstractColumnCss;
import cz.tomasdvorak.cars.wicket.components.table.AbstractListDataProvider;
import cz.tomasdvorak.cars.wicket.components.table.EnhancedDataTable;
import cz.tomasdvorak.cars.wicket.components.table.PropertyColumnCss;
import org.apache.log4j.Logger;
import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.*;

import java.util.Date;
import java.util.List;

@AuthorizeInstantiation(Auth.USER)
public class StatsPage extends BasePage {

    private static final Logger log = Logger.getLogger(StatsPage.class);

    private ExpenseCriteria criteria;
    private static final int ITEMS_PER_PAGE = 50;


    private final class StatsDataProvider extends AbstractListDataProvider<Expense> {

        protected List<Expense> loadData() throws Exception {
            List<Expense> data = StatsPage.this.getExpensesDao().getAll(StatsPage.this.criteria);
            String sortProperty = null;
            Boolean sortAsc;
            SortParam sortParam = getSort();
            if (sortParam != null) {
                sortProperty = sortParam.getProperty();
                sortAsc = sortParam.isAscending();
                ExpenseSort.valueOf(sortProperty).sort(data, sortAsc);
            }

            return data;
        }
    }

    private final class StatsCriteriaForm extends Form<ExpenseCriteria> {

        private Vehicle vehicle;

        public StatsCriteriaForm(String id, IModel<ExpenseCriteria> model) {
            super(id, model);
            this.vehicle = model.getObject().getVehicle() != null ? StatsPage.this.getVehiclesDao()
                    .getById(model.getObject().getVehicle()) : null;
            add(new TextField<Date>("dateFrom").add(new DatePicker()));
            add(new TextField<Date>("dateTill").add(new DatePicker()));
            add(new DropDownChoice<Vehicle>("vehicle", new PropertyModel<Vehicle>(this, "vehicle"),
                    getAvailableVehicles(), new IChoiceRenderer<Vehicle>() {
                        public Object getDisplayValue(Vehicle object) {
                            return object.toString();
                        }

                        public String getIdValue(Vehicle object, int index) {
                            return "" + object.getId();
                        }
                    }));

            add(new DropDownChoice<ExpenseType>("expenseType", Lists.arrayList(ExpenseType.values()),
                    new IChoiceRenderer<ExpenseType>() {
                        public Object getDisplayValue(ExpenseType object) {
                            return getLocalizer().getString("type." + object.name(),
                                    StatsPage.this);
                        }

                        public String getIdValue(ExpenseType object, int index) {
                            return object.name();
                        }
                    }));
        }

        @Override
        protected void onSubmit() {
            this.getModelObject().setVehicle(this.vehicle != null ? this.vehicle.getId() : null);
            try {
                setResponsePage(new StatsPage(this.getModelObject()));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        private List<Vehicle> getAvailableVehicles() {
            return StatsPage.this.getVehiclesDao().getAllVehicles(null);
        }
    }

    public StatsPage() throws Exception {
        this(new ExpenseCriteria());
    }

    public StatsPage(ExpenseCriteria criteria) {
        this.criteria = criteria;
        add(new StatsCriteriaForm("criteria", new CompoundPropertyModel<ExpenseCriteria>(this.criteria)));
        IColumn<Expense>[] columns = Lists.array(
                new PropertyColumnCss<Expense>("col1", new ResourceModel("expenseType"), "type"),
                new PropertyColumnCss<Expense>("col2", new ResourceModel("date"), "date"),
                new PropertyColumnCss<Expense>("col3", new ResourceModel("mileage"), "mileage"),
                new PropertyColumnCss<Expense>("col5", new ResourceModel("price"), "price"),
                new PropertyColumnCss<Expense>("col6", new ResourceModel("personId"), "personId"),
                new AbstractColumnCss<Expense>("col7", new ResourceModel("vehicleId"), "vehicleId"){
                    public void populateItem(Item<ICellPopulator<Expense>> cellItem,
                                             String componentId, IModel<Expense> rowModel) {
                        String vehicle = "";
                        int vehicleId = rowModel.getObject().getVehicleId();
                        if(vehicleId > -1) {
                            vehicle = StatsPage.this.getVehiclesDao().getById(vehicleId).toString();
                        }
                        cellItem.add(new Label(componentId, vehicle));
                    }
                }
                );

        StatsDataProvider dataProvider = new StatsDataProvider();
        EnhancedDataTable<Expense> table = new EnhancedDataTable<Expense>("table", columns,
                dataProvider, ITEMS_PER_PAGE);

        List<Expense> expenses = Lists.arrayList();

        try {
        expenses = dataProvider.loadData();
        } catch (Exception e) {
            log.error(e);
        }
        int gasLiters = 0;
        int gasPrice = 0;
        for(Expense e : expenses) {
            if(ExpenseType.GAS.equals(e.getType())) {
                gasLiters += e.getQuantity();
                gasPrice += e.getPrice();
            }
        }
        add(new Label("gasLiters", new Model<Integer>(gasLiters)));
        add(new Label("gasPrice", new Model<Integer>(gasPrice)));
        add(table);

    }

    protected List<BreadcrumbItem> getPageBreadcrumb() throws Exception {
        return Lists.arrayList(new BreadcrumbItem(new ResourceModel("breadcrumb.stats")));
    }
}
